
#===============================================================================
#
#         FILE:  SOURCE.pm
#
#  DESCRIPTION:  
#
#        FILES:  ---
#         BUGS:  ---
#        NOTES:  ---
#       AUTHOR:  Beomsu Chang (bschang), <bschang@phya.yonsei.ac.kr>
#      COMPANY:  
#      VERSION:  1.0
#      CREATED:  
#     REVISION:  ---
#===============================================================================

package WebTranslate::Source; {
use strict;
use Object::InsideOut qw/WebTranslate::Base/;
use IO::File;
use IO::Scalar;
use IO::String;
use WebTranslate::Function;

########## Declare Data Members ##########

my @Data		:Field :All(Data);
my @FileName	:Field :All(FileName);
my @Name		:Field :All(Name);
my @Lang		:Field :All(Lang);
my @Ver			:Field :All(Ver);
my @Meta		:Field :All(Meta);

my @Units		:Field :All(Units)		:Type(list);
my @UnitList	:Field :All(UnitList)	:Type(list);
my @UnitHash	:Field :All(UnitHash)	:Type(list);

my @UnitTagItemList	:Field	:All(UnitTagItemList)	:Type(list);
my @MetaTagItemList	:Field	:All(MetaTagItemList)	:Type(list);

my @TagNameHash		:Field	:All(TagNameHash);

# Any TAG Template string must include '%%ATTRIBUTE%%'
my @TagTemplate			:Field :All(TagTemplate);
my @AttributeTemplate	:Field :All(AttributeTemplate);
my @TagCharicterTable	:Field :All(TagCharicterTable) 	:Type(hash);
my @TagNameHash			:Field :All(TagNameList)		:Type(hash);
my @TagRegx				:Field :All(TagRegx);
my @TagStr				:Field :All(TagStr);
my @AttrRegx			:Field :All(AttrRegx);
my @AttrStr				:Field :All(AttrStr);

########## Inner Method ########

# Init method, Overide this in MyClass
sub _init	:Init {
	my ( $self, $args ) = @_;
	$self->Units	( [] );
	$self->UnitList	( [] );
	$self->UnitHash	( {} );

	$self->UnitTagItemList	( [ qw/Sec Unit Lang/ ] 			);
	$self->MetaTagItemList	( [ qw/Name FileName Ver Lang/ ]	);

	$self->TagNameHash	( {Unit => 'UNIT',	Meta => 'META', Comment => 'C',} );

	# parameters are (TagName, Attribute String) and Tag String
	# ex) X<<<WT_UNIT value key1="value1",key2="value2">>>
	$self->TagTemplate ({
		ToStr	=>sub { 'X<WT_'.$_[0].' '.$_[1].'>' },
		FromStr	=>sub { ($_[0]=~/X<WT_(\S*)"\s*(.*)>"/) },
	});
    
	$self->TagRegx( qr/^X<WT_(?:UNIT|META|C)\s*.*?>/ );
	# parameter are Attribute String and Attribute hash reference
	$self->AttributeTemplate ({
		ToStr	=>sub { join ',', map{$_->[0].'="'.$_->[1].'"'} %{$_[0]}; },
		FromStr	=>sub { my %at; $at{$1}=$2 while /(\w*)="(.*?)"/g; \%at; },
	});
}



########## Default Method (Maybe not overload)
sub unitizeSrc {
	my ( $self, $content ) = @_;
	my $parser = WebTranslate::PodParser->new;
	my $sh = IO::Scalar->new(\$content);
	$parser->parse_from_filehandle( IO::Scalar->new(\$content) );

	my $lang	= $self->Lang();
	for my $para (@{$parser->getWT_DATA()}){
		$para->{attr('Lang')} = $lang;
		$self->makeUnit($para);
	}
}


sub parseX{
	my ($self) = shift;
	my $tagregx  = $self->TagRegx;
 
	my $sh = IO::Scalar(\{$self->Data});
	$self->clearUnits();
	my ($unit,$flag);

	for(<$sh>){
		if(/(tagregx)/) {
			my ($tag,$attr) = $self->get_TagAttr($1);
			if($tag=~/UNIT/i){
				$unit=$self->makeUnit($attr); $flag='UNIT';
			}elsif($tag=~/META/i){
				$self->setMeta($attr); $flag='META';
			}
		}else{
			$unit->addContent($_) if $unit && $flag eq 'UNIT';
		}
	}
	$self->clearData();
}


sub get_TagStr {  
	my ( $self, $tag, $attr ) = @_;
	my $tagname 	= $self->TagNameHash->{attr($tag)};
	my $attrString 	= $self->AttributeTemplate->{'ToStr'}->($attr);
	my $tagString 	= $self->TagTemplate->{'ToStr'}->($tagname,$attrString);
	return $tagString;
}

sub get_TagAttr {
	my ( $self, $tagstr ) = @_;
	my ($tagname,$attrstr) = $self->TagTemplate->{'FromStr'}->($tagstr);
	my $attr = $self->AttributeTemplate->{'FromStr'}->($attrstr);
	return $tagname,$attr;
}

sub loadX{
	my ($self,$file) = @_;
	$self->loadFile($file);
	$self->parseX();
}

sub loadFile {
	my $self = shift;
	my $filename = shift;
	$FileName[$$self] = $filename;
	{
		local $/;
		open my $tmpfh, "<", $filename or die "Cannot open $filename :$!";;
		$Data[$$self] = <$tmpfh>;
		close $tmpfh;
	}
}

sub saveFile{
	my $self = shift;
	open my $fh, ">", shift;
	print $fh $Data[$$self];
	close $fh;
}

sub LoadSrcFile {
	my ($self,$file) = @_;
	my $fh = IO::File->new($file);
	my $content;
	{
		local $/=undef;
		$content = <$fh>;
	}
	$self->LoadSrcStr($content);
	$fh->close();
}

sub LoadSrcStr {
	my ( $self, $content ) = @_;
	$self->clearUnits();
	$self->unitizeSrc($content);
}

sub makeUnit {
	my ($self,$attr) = @_;
	my $units = $self->Units;
	my $unit = WebTranslate::Unit->new($attr);
	push @$units, $unit if defined $unit;
}

sub clearData { my $self = shift; $self->Data(''); }

sub clearUnits {
	my $self = shift; 
	$self->Units([]);
}

sub clearAll {
	my $self = shift;
	$self->clearData();
	$self->clearUnits;
}

sub setMeta {
	my ($self, $meta) = @_;
	$self->Meta($meta);
	$self->Name($meta->{Name});
	$self->Lang($meta->{Lang});
	$self->Ver ($meta->{Ver} );
}


sub mergeUnits {
	my ($self,%attr)= shift;
	my $release = 1 if $attr{'Release'} || $attr{'release'};
	my $data;
	$data .= $self->get_TagStr('Meta',$self->Meta);

	for my $unit ( @{$self->Units()} ){
		$data .= $self->get_TagStr('Unit',$unit->getAttr())."\n" unless $release;
		$data .= $unit->getContent();
		
	}
	$self->Data($data);
}


	

### default Method (Usally overload)

#### Virtual Method


########## Useful Function ##########


} # End of Package
1;
